/////////////////////////////////////////////////////////////////////////////////
// Paint.NET
// Copyright (C) Rick Brewster, Chris Crosetto, Dennis Dietrich, Tom Jackson, 
//               Michael Kelsey, Brandon Ortiz, Craig Taylor, Chris Trevino, 
//               and Luke Walker
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.
// Adapted for PocketPicture by Dmitry Osinovsky
// See LicenseMIT.txt for complete licensing and attribution information.
/////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace OsdmSoftware.PocketPicture
{
    public struct PointF
    {
        public float X;
        public float Y;

        public PointF(float x, float y) { X = x; Y = y; }
        public PointF(Point p) { X = p.X; Y = p.Y; }

        public static implicit operator PointF(Point value)
        {
            return new PointF(value);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (int) (X * Y);
            }
        }
        public override bool Equals(object obj)
        {
            return (obj is PointF) && (((PointF) obj) == this);
        }

        public static bool operator ==(PointF left, PointF right)
        {
            return Math.Abs(left.X - right.X) <= Single.Epsilon && Math.Abs(left.Y - right.Y) <= Single.Epsilon;
        }

        public static bool operator !=(PointF left, PointF right)
        {
            return !(left == right);
        }
    }

    /// <summary>
    /// Defines miscellaneous constants and static functions.
    /// </summary>
    public sealed class Utility
    {
        public static RectangleF RectangleFromCenter(PointF center, float halfSize)
        {
            RectangleF ret = new RectangleF(center.X, center.Y, 0, 0);
            ret.X -= halfSize;
            ret.Y -= halfSize;
            ret.Width += halfSize * 2;
            ret.Height += halfSize * 2;
            //ret.Inflate(halfSize, halfSize);
            return ret;
        }

        /// <summary>
        /// Returns the Magnitude (distance to origin) of a point
        /// </summary>
        public static float Magnitude(PointF p)
        {
            return (float) Math.Sqrt(p.X * p.X + p.Y * p.Y);
        }

        public static byte ClampToByte(double x)
        {
            if (x > 255)
            {
                return 255;
            }
            else if (x < 0)
            {
                return 0;
            }
            else
            {
                return (byte) x;
            }
        }

        public static byte ClampToByte(float x)
        {
            if (x > 255)
            {
                return 255;
            }
            else if (x < 0)
            {
                return 0;
            }
            else
            {
                return (byte) x;
            }
        }

        public static byte ClampToByte(int x)
        {
            if (x > 255)
            {
                return 255;
            }
            else if (x < 0)
            {
                return 0;
            }
            else
            {
                return (byte) x;
            }
        }

        public static int LerpIntPercent(int from, int to, int percent)
        {
            return (from * (100 - percent) + to * percent) / 100;
        }

        public static float Lerp(float from, float to, float frac)
        {
            return (from * (1 - frac) + to * frac);
        }

        public static double Lerp(double from, double to, double frac)
        {
            return (from * (1 - frac) + to * frac);
        }

        public static bool RGBEqual(Color a, Color b, int tolerance)
        {
            int sum = 0;
            int diff;

            diff = a.R - b.R;
            sum += (diff * diff);

            diff = a.G - b.G;
            sum += (diff * diff);

            diff = a.B - b.B;
            sum += (diff * diff);

            return (sum <= tolerance * tolerance * 4);
        }

        public static bool RGBEqual(ColorBgra a, ColorBgra b, int tolerance)
        {
            int sum = 0;
            int diff;

            diff = a.R - b.R;
            sum += (diff * diff);

            diff = a.G - b.G;
            sum += (diff * diff);

            diff = a.B - b.B;
            sum += (diff * diff);

            return (sum <= tolerance * tolerance * 4);
        }

        public static bool RGBEqual(Color a, Color b)
        {
            return (a.R == b.R && a.G == b.G && a.B == b.B);
        }
    }
}
